#include "comm.hpp" // 包含自定义的头文件，通常包含共享内存和日志相关的声明

extern Log log; // 声明一个外部的日志对象

int main()
{
    Init init; // 初始化对象，用于初始化环境（具体实现细节在comm.hpp中）

    int shmid = CreateShm(); // 创建共享内存，并返回共享内存段标识符
    char *shmaddr = (char*)shmat(shmid, nullptr, 0); // 将共享内存段附加到进程的地址空间，并返回指向共享内存的指针

    // IPC（进程间通信）代码在这里
    // 一旦有人把数据写入到共享内存中，我们能立刻看到数据，不需要经过系统调用，直接访问共享内存

    int fd = open(FIFO_FILE, O_RDONLY); // 以只读方式打开命名管道
    // 等待写入方打开管道后，当前进程才会继续执行，open函数会阻塞直到管道另一端被打开
    if (fd < 0)
    {
        log(Fatal, "error string: %s, error code: %d", strerror(errno), errno); // 记录打开管道失败的日志
        exit(FIFO_OPEN_ERR); // 退出程序，返回管道打开错误码
    }

    struct shmid_ds shmds; // 定义共享内存数据结构，用于存储共享内存段的信息
    while(true)
    {
        char c; // 用于读取管道中的数据
        ssize_t s = read(fd, &c, 1); // 从管道中读取一个字节的数据
        if(s == 0) break; // 读取到文件末尾，退出循环
        else if(s < 0) break; // 读取出错，退出循环

        cout << "client say@ " << shmaddr << endl; // 直接从共享内存中读取数据并输出
        sleep(1); // 睡眠1秒

        shmctl(shmid, IPC_STAT, &shmds); // 获取共享内存段的状态，并存储在shmds结构中
        cout << "shm size: " << shmds.shm_segsz << endl; // 输出共享内存段的大小
        cout << "shm nattch: " << shmds.shm_nattch << endl; // 输出当前附加到共享内存段的进程数
        printf("shm key: 0x%x\n",  shmds.shm_perm.__key); // 输出共享内存段的键值
        cout << "shm mode: " << shmds.shm_perm.mode << endl; // 输出共享内存段的访问模式
    }

    shmdt(shmaddr); // 将共享内存段从当前进程分离
    shmctl(shmid, IPC_RMID, nullptr); // 标记共享内存段为删除

    close(fd); // 关闭管道文件描述符
    return 0; // 正常退出程序
}
